﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Xml;
using System.IO;
using RestInstaller.Properties;

namespace RestInstaller {

    struct ServiceInfo {
        public string ID { get; set; }
        public string Name { get; set; }
        public string Port { get; set; }
    }

    class Program {
        static string[] services = new string[] { };
        static string filename = "rest.cmd";
        static Regex serviceRegex = new Regex(@"services=(?<Services>.*)", RegexOptions.Compiled | RegexOptions.IgnoreCase);
        static readonly string appcmd = String.Format(@"{0}\system32\inetsrv\appcmd.exe", Environment.GetEnvironmentVariable("systemroot"));

        static void Main(string[] args) {
            System.IO.Directory.SetCurrentDirectory(System.AppDomain.CurrentDomain.BaseDirectory);
            var argsValue = String.Join(" ", args);
            var isInstall = args.Length > 0 && args[0] == "install";
            var serviceMatch = serviceRegex.Match(argsValue);
            if (serviceMatch.Success)
                services = serviceMatch.Groups["Services"].Value.Split(',');
            if (isInstall) Install();
            else UnInstall();
            var fileInfo = new FileInfo(filename);
            if (fileInfo.Exists) fileInfo.Delete();
        }

        static void CreateBatFile(ServiceInfo serviceInfo, bool install) {
            var bat = install ? Resources.InstallTemplate : Resources.UnInstallTemplate;
            bat = bat.Replace("[Name]", serviceInfo.Name)
                .Replace("[ID]", serviceInfo.ID)
                .Replace("[Port]", serviceInfo.Port);
            using (var sw = new StreamWriter(filename, false)) {
                sw.WriteLine(bat);
                sw.Flush();
            }
        }

        static void ExecuteBatFile(bool install) {
            foreach (var serviceInfo in ServiceInfos) {
                CreateBatFile(serviceInfo, install);
                ExecuteFile(filename, string.Empty);
                if (install) {
                    var ruleName = String.Join(serviceInfo.Name, serviceInfo.Port);
                    ExecuteFile("netsh.exe", String.Format("advfirewall firewall delete rule name=\"{0}\"", ruleName));
                    ExecuteFile("netsh.exe", String.Format("advfirewall firewall add rule name=\"{0}\" dir=in action=allow protocol=TCP localport={1}", ruleName, serviceInfo.Port));
                }
            }
        }

        static void UnInstall() {
            ExecuteBatFile(false);
        }

        static void Install() {
            ExecuteBatFile(true);
        }

        static IEnumerable<ServiceInfo> ServiceInfos {
            get {
                var doc = new XmlDocument();
                doc.Load("services.xml");
                var serviceInfos = doc.GetElementsByTagName("service").Cast<XmlElement>()
                    .Select(element => new ServiceInfo()
                    {
                        ID = element.Attributes["id"].Value,
                        Name = element.Attributes["name"].Value,
                        Port = element.Attributes["port"].Value
                    });
                serviceInfos = services.Length > 0 ?
                serviceInfos.Where(serviceInfo => services.Any(service => serviceInfo.Name == service)) : serviceInfos;
                return serviceInfos;
            }
        }

        static void ExecuteFile(string filename, string arguments) {
            ProcessStartInfo info = new ProcessStartInfo(filename);
            info.Arguments = arguments;
            info.UseShellExecute = true;
            info.CreateNoWindow = true;
            info.ErrorDialog = false;
            info.WorkingDirectory = AppDomain.CurrentDomain.BaseDirectory;
            info.WindowStyle = ProcessWindowStyle.Hidden;
            var process = Process.Start(info);
            process.WaitForExit();
        }
    }
}
